package com.macro.mall.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.util.StringUtil;
import com.macro.mall.dao.*;
import com.macro.mall.dto.PmsProductParam;
import com.macro.mall.dto.PmsProductQueryParam;
import com.macro.mall.dto.PmsProductResult;
import com.macro.mall.mapper.CmsPrefrenceAreaProductRelationMapper;
import com.macro.mall.mapper.CmsSubjectProductRelationMapper;
import com.macro.mall.mapper.PmsMemberPriceMapper;
import com.macro.mall.mapper.PmsProductAttributeValueMapper;
import com.macro.mall.mapper.PmsProductFullReductionMapper;
import com.macro.mall.mapper.PmsProductLadderMapper;
import com.macro.mall.mapper.PmsProductMapper;
import com.macro.mall.mapper.PmsSkuStockMapper;
import com.macro.mall.model.*;
import com.macro.mall.service.PmsProductService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName PmsProductServiceImpl
 * @Description 商品管理Service实现类
 * @Author lin.dai
 * @Version 1.0
 **/
@Service
public class PmsProductServiceImpl
	implements PmsProductService {

	//创建日志实例，那么为什么要用static还有final呢？？
	//   1、 定义成static final,logger变量不可变，读取速度快
	//    2、static 修饰的变量是不管创建了new了多少个实例，也只创建一次，节省空间，如果每次都创建Logger的话比较浪费内存；final修饰表示不可更改，常量
	//    3、将域定义为static,每个类中只有一个这样的域.而每一个对象对于所有的实例域却都有自己的一份拷贝.，用static修饰既节约空间，效率也好。final 是本 logger 不能再指向其他 Logger 对象
	private static final Logger LOGGER = LoggerFactory.getLogger(PmsProductServiceImpl.class);

	@Autowired
	private PmsProductDao pmsProductDao;
	@Autowired
	private PmsProductMapper productMapper;
	@Autowired
	private PmsMemberPriceDao memberPriceDao;
	@Autowired
	private PmsMemberPriceMapper memberPriceMapper;
	@Autowired
	private PmsProductLadderDao productLadderDao;
	@Autowired
	private PmsProductLadderMapper productLadderMapper;
	@Autowired
	private PmsProductFullReductionDao productFullReductionDao;
	@Autowired
	private PmsProductFullReductionMapper productFullReductionMapper;
    @Autowired
    private PmsSkuStockDao skuStockDao;
    @Autowired
    private PmsSkuStockMapper skuStockMapper;
    @Autowired
    private PmsProductAttributeValueDao productAttributeValueDao;
    @Autowired
    private PmsProductAttributeValueMapper productAttributeValueMapper;
    @Autowired
    private CmsSubjectProductRelationDao subjectProductRelationDao;
    @Autowired
    private CmsSubjectProductRelationMapper subjectProductRelationMapper;
    @Autowired
    private CmsPrefrenceAreaProductRelationDao prefrenceAreaProductRelationDao;
    @Autowired
    private CmsPrefrenceAreaProductRelationMapper prefrenceAreaProductRelationMapper;
	@Autowired
	private PmsProductVertifyRecordDao productVertifyRecordDao;

	@Override
	public int create(PmsProductParam productParam) {
		int count;
		//创建商品信息
		PmsProduct product = productParam;
		product.setId(null);
		productMapper.insertSelective(product);
		//根据促销类型设置价格：会员价格、阶梯价格、满减价格
		Long productId = product.getId();
		//会员价格
		relateAndInsertList(memberPriceDao, productParam.getMemberPriceList(), productId);
		//阶梯价格
		relateAndInsertList(productLadderDao, productParam.getProductLadderList(), productId);
		//满减价格
		relateAndInsertList(productFullReductionDao, productParam.getProductFullReductionList(), productId);
		//处理sku编码
		handleSkuStockCode(productParam.getSkuStockList(), productId);
		//添加sku库存信息
		relateAndInsertList(skuStockDao, productParam.getSkuStockList(), productId);
		//添加商品参数,添加自定义商品规格
		relateAndInsertList(productAttributeValueDao, productParam.getProductAttributeValueList(), productId);
		//关联专题
		relateAndInsertList(subjectProductRelationDao, productParam.getSubjectProductRelationList(), productId);
		//关联优选
		relateAndInsertList(prefrenceAreaProductRelationDao, productParam.getPrefrenceAreaProductRelationList(), productId);
		count = 1;
		return count;
	}

	/**
	 * 此方法是根据所填写的信息生成sku编码
	 * @param skuStockList
	 * @param productId
	 */
	private void handleSkuStockCode(List<PmsSkuStock> skuStockList, Long productId) {
		if(CollectionUtils.isEmpty(skuStockList)){
			for (int i = 0; i < skuStockList.size(); i++) {
				PmsSkuStock skuStock = skuStockList.get(i);
				if(StringUtil.isEmpty(skuStock.getSkuCode())){
					SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
					/**
					 * 运行速度快慢为：StringBuilder > StringBuffer > String
					 * StringBuilder是线程不安全的，而StringBuffer是线程安全的
					 * 	   String：适用于少量的字符串操作的情况,不可更改
					 * 　　StringBuilder：适用于单线程下在字符缓冲区进行大量操作的情况
					 * 　　StringBuffer：适用多线程下在字符缓冲区进行大量操作的情况，不可更改
					 */
					StringBuilder sb = new StringBuilder();
					//日期
					sb.append(sdf.format(new Date()));
					//四位商品id,作用是左边补零凑足四位
					sb.append(String.format("%04d",productId));
					//三位索引id,作用是左边补零凑足三位
					sb.append(String.format("%03d", i+1));
					skuStock.setSkuCode(sb.toString());
				}
			}
		}
	}

	@Override
	public int update(Long id, PmsProductParam productParam) {
		int count;
		//创建商品信息
		PmsProduct product = productParam;
		product.setId(id);
		productMapper.updateByPrimaryKeySelective(product);
		//会员价格
		PmsMemberPriceExample pmsMemberPriceExample = new PmsMemberPriceExample();
		pmsMemberPriceExample.createCriteria().andProductIdEqualTo(id);
		memberPriceMapper.deleteByExample(pmsMemberPriceExample);
		relateAndInsertList(memberPriceDao,productParam.getMemberPriceList(),id);
		//阶梯价格
		PmsProductLadderExample pmsProductLadderExample = new PmsProductLadderExample();
		pmsMemberPriceExample.createCriteria().andProductIdEqualTo(id);
		productLadderMapper.deleteByExample(pmsProductLadderExample);
		relateAndInsertList(productLadderDao,productParam.getProductLadderList(),id);
		//满减价格
		PmsProductFullReductionExample pmsProductFullReductionExample = new PmsProductFullReductionExample();
		pmsProductFullReductionExample.createCriteria().andProductIdEqualTo(id);
		productFullReductionMapper.deleteByExample(pmsProductFullReductionExample);
		relateAndInsertList(productFullReductionDao,productParam.getProductFullReductionList(),id);
		//修改sku信息库存信息
		handleUpdateSkuStockList(id,productParam);
		//修改商品属性,添加商品参数,添加自定义商品规格
		PmsProductAttributeValueExample pmsProductAttributeValueExample = new PmsProductAttributeValueExample();
		pmsProductAttributeValueExample.createCriteria().andProductIdEqualTo(id);
		productAttributeValueMapper.deleteByExample(pmsProductAttributeValueExample);
		relateAndInsertList(productAttributeValueDao,productParam.getProductAttributeValueList(),id);
		//关联专题
		CmsSubjectProductRelationExample cmsSubjectProductRelationExample = new CmsSubjectProductRelationExample();
		cmsSubjectProductRelationExample.createCriteria().andProductIdEqualTo(id);
		subjectProductRelationMapper.deleteByExample(cmsSubjectProductRelationExample);
		relateAndInsertList(subjectProductRelationDao,productParam.getSubjectProductRelationList(),id);
		//关联优选
		CmsPrefrenceAreaProductRelationExample cmsPrefrenceAreaProductRelationExample = new CmsPrefrenceAreaProductRelationExample();
		cmsPrefrenceAreaProductRelationExample.createCriteria().andProductIdEqualTo(id);
		prefrenceAreaProductRelationMapper.deleteByExample(cmsPrefrenceAreaProductRelationExample);
		relateAndInsertList(productAttributeValueDao,productParam.getPrefrenceAreaProductRelationList(),id);
		count = 1;
		return count;
	}

	@Override
	public List<PmsProduct> list(PmsProductQueryParam productQueryParam, Integer pageSize, Integer pageNum) {
		PageHelper.startPage(pageNum,pageSize);
		PmsProductExample pmsProductExample = new PmsProductExample();
		PmsProductExample.Criteria criteria = pmsProductExample.createCriteria();
		//0表示未删除的的记录
		criteria.andDeleteStatusEqualTo(0);
		//上架状态
		if (productQueryParam.getPublishStatus() != null) {
			criteria.andPublishStatusEqualTo(productQueryParam.getPublishStatus());
		}
		//审核状态
		if (productQueryParam.getVerifyStatus() != null) {
			criteria.andVerifyStatusEqualTo(productQueryParam.getVerifyStatus());
		}
		//输入搜索，模糊搜索
		if (!StringUtils.isEmpty(productQueryParam.getKeyword())) {
			criteria.andNameLike("%" + productQueryParam.getKeyword() + "%");
		}
		//商品货号
		if (!StringUtils.isEmpty(productQueryParam.getProductSn())) {
			criteria.andProductSnEqualTo(productQueryParam.getProductSn());
		}
		//商品品牌
		if (productQueryParam.getBrandId() != null) {
			criteria.andBrandIdEqualTo(productQueryParam.getBrandId());
		}
		//商品分类
		if (productQueryParam.getProductCategoryId() != null) {
			criteria.andProductCategoryIdEqualTo(productQueryParam.getProductCategoryId());
		}
		return productMapper.selectByExample(pmsProductExample);
	}

	@Override
	public List<PmsProduct> list(String keyword) {
		PmsProductExample productExample = new PmsProductExample();
		PmsProductExample.Criteria criteria = productExample.createCriteria();
		criteria.andDeleteStatusEqualTo(0);
		if(!StringUtil.isEmpty(keyword)){
			criteria.andNameLike("%" + keyword + "%");
			productExample.or().andDeleteStatusEqualTo(0).andProductSnLike("%" + keyword + "%");
		}
		return productMapper.selectByExample(productExample);
	}

	@Override
	public int updateVerifyStatus(List<Long> ids, Integer verifyStatus, String detail) {
		PmsProduct product = new PmsProduct();
		product.setVerifyStatus(verifyStatus);
		PmsProductExample example = new PmsProductExample();
		example.createCriteria().andIdIn(ids);
		List<PmsProductVertifyRecord> list = new ArrayList<>();
		int count = productMapper.updateByExampleSelective(product, example);
		//修改完审核状态后插入审核记录
		for (Long id : ids) {
			PmsProductVertifyRecord record = new PmsProductVertifyRecord();
			record.setProductId(id);
			record.setCreateTime(new Date());
			record.setDetail(detail);
			record.setStatus(verifyStatus);
			record.setVertifyMan("test");
			list.add(record);
		}
		productVertifyRecordDao.insertList(list);
		return count;
	}

	@Override
	public int updatePublishStatus(List<Long> ids, Integer publishStatus) {
		PmsProduct record = new PmsProduct();
		record.setPublishStatus(publishStatus);
		PmsProductExample example = new PmsProductExample();
		example.createCriteria().andIdIn(ids);
		return productMapper.updateByExampleSelective(record, example);
	}

	@Override
	public int updateRecommendStatus(List<Long> ids, Integer recommendStatus) {
		PmsProduct record = new PmsProduct();
		record.setRecommandStatus(recommendStatus);
		PmsProductExample example = new PmsProductExample();
		example.createCriteria().andIdIn(ids);
		return productMapper.updateByExampleSelective(record, example);
	}

	@Override
	public int updateNewStatus(List<Long> ids, Integer newStatus) {
		PmsProduct record = new PmsProduct();
		record.setNewStatus(newStatus);
		PmsProductExample example = new PmsProductExample();
		example.createCriteria().andIdIn(ids);
		return productMapper.updateByExampleSelective(record, example);
	}

	@Override
	public int updateDeleteStatus(List<Long> ids, Integer deleteStatus) {
		PmsProduct record = new PmsProduct();
		record.setDeleteStatus(deleteStatus);
		PmsProductExample example = new PmsProductExample();
		example.createCriteria().andIdIn(ids);
		return productMapper.updateByExampleSelective(record, example);
	}

	//更新sku库存信息
	private void handleUpdateSkuStockList(Long id, PmsProductParam productParam) {
		//当前sku信息,此信息中包含新增的部分（id为null）,和需要修改的部分id不为null
		List<PmsSkuStock> skuStockList = productParam.getSkuStockList();
		//如果当前修改时，没有sku则直接删除
		if(CollectionUtils.isEmpty(skuStockList)){
			PmsSkuStockExample pmsSkuStockExample = new PmsSkuStockExample();
			pmsSkuStockExample.createCriteria().andProductIdEqualTo(id);
			skuStockMapper.deleteByExample(pmsSkuStockExample);
			//此处retrun表明，当执行到此后。便不再执行后续语句了。直接跳出
			// 即return 执行之后，将退出所在的方法，而不再执行后面没有执行的语句
			return;
		}
		//获取初始sku信息
		PmsSkuStockExample pmsSkuStockExample = new PmsSkuStockExample();
		pmsSkuStockExample.createCriteria().andProductIdEqualTo(id);
		List<PmsSkuStock> oriSkuStocks = skuStockMapper.selectByExample(pmsSkuStockExample);
		//获取新增sku信息
		//传统写法
		/*ArrayList<PmsSkuStock> insertSkuList = new ArrayList<>();
		ArrayList<PmsSkuStock> updateSkuList = new ArrayList<>();
		for (PmsSkuStock pmsSkuStock : skuStockList) {
			if(pmsSkuStock.getId()==null){
				insertSkuList.add(pmsSkuStock);
			}else{
				updateSkuList.add(pmsSkuStock);
			}
		}*/
		//java8写法
		List<PmsSkuStock> insertSkuList = skuStockList.stream().filter(item -> item.getId() == null).collect(Collectors.toList());
		List<PmsSkuStock> updateSkuList = skuStockList.stream().filter(item -> item.getId() != null).collect(Collectors.toList());
		List<Long> updateSkuIds = updateSkuList.stream().map(PmsSkuStock::getId).collect(Collectors.toList());
		//获取需要删除的sku信息
		List<PmsSkuStock> removeSkuList = oriSkuStocks.stream().filter(item -> !updateSkuIds.contains(item.getId())).collect(Collectors.toList());
		handleSkuStockCode(insertSkuList,id);
		handleSkuStockCode(updateSkuList,id);
		//新增sku
		if(CollUtil.isNotEmpty(insertSkuList)){
			relateAndInsertList(skuStockDao,insertSkuList,id);
		}
		//删除sku
		if(CollUtil.isNotEmpty(removeSkuList)){
			List<Long> removeSkuIds = removeSkuList.stream().map(PmsSkuStock::getId).collect(Collectors.toList());
			PmsSkuStockExample removeExample = new PmsSkuStockExample();
			removeExample.createCriteria().andIdIn(removeSkuIds);
			skuStockMapper.deleteByExample(removeExample);
		}
		//修改
		if(CollUtil.isNotEmpty(updateSkuList)){
			for (PmsSkuStock pmsSkuStock : updateSkuList) {
				skuStockMapper.updateByPrimaryKeySelective(pmsSkuStock);
			}
		}
	}

	@Override
	public PmsProductResult getUpdateInfo(Long id) {
		return pmsProductDao.getUpdateInfo(id);
	}


	/**
	 * 建立和插入关系表操作
	 * TODO反射++++++++
	 *
	 * @param dao       可以操作的dao
	 * @param dataList  要插入的数据
	 * @param productId 建立关系的id
	 */
	private void relateAndInsertList(Object dao, List dataList, Long productId) {
		//CollectionUtils.isEmpty()判断集合是否为空，当集合为null时，不会报错
		//与list.isEmpty()q区别在于List这个IsEmpty()方法为什么没有把null包括进去，当集合为null时，则会报NullPointerException
		if (CollectionUtils.isEmpty(dataList)) {
			return;
		}
		try {
			for (Object item : dataList) {
				//或获取item对象的setId方法，由于setId的方法形参是long类型的，所以parameterTypes为Long.class
				Method setId = item.getClass().getMethod("setId", Long.class);
				setId.invoke(item, (Long) null);
				Method setProductId = item.getClass().getMethod("setProductId", Long.class);
				setProductId.invoke(item, productId);
			}
			Method insertList = dao.getClass().getMethod("insertList", List.class);
		} catch (Exception e) {
			LOGGER.warn("创建产品出错:{}", e.getMessage());
			throw new RuntimeException(e.getMessage());
		}
	}

}
